<template>
  <div :id="vditorId" class="vditor" :class="{ 'vditor-hidden': showPreview }"></div>
</template>

<script setup lang="ts">
import {onMounted, shallowRef, ref, reactive, PropType} from "vue";
import Vditor from "vditor";
import "vditor/dist/index.css";
import { ElMessage } from "element-plus";
import { uploadMultiApi } from "@/api/modules/file.ts";

const props = defineProps({
  height: {
    type: [Number, String],
    default: "450px",
  },
  modelValue: {
    type: String,
    default: "",
  },
  language: {
    type: String,
    default: "zh_CN",
  },
  showPreview: {
    type: Boolean,
    default: false,
  },
  currentTheme: {
    type: String as PropType<"classic" | "dark" | undefined>,
    default: "classic",
  },
  // 额外的formData参数
  extraData: {
    type: Object,
    default: () => ({}),
  },
  placeholder: {
    type: String,
    default: "",
  },
});

const vditorId = ref(
    "vditor-" + +new Date() + ((Math.random() * 1000).toFixed(0) + "")
);

const vditorEditor = shallowRef();
onMounted(() => {
  vditorEditor.value = initVditorEditor();
});

const emits = defineEmits([
  "update:modelValue",
]);

const toolbars = [
  'emoji',
  'headings',
  'bold',
  'italic',
  'strike',
  'link',
  '|',
  'list',
  'ordered-list',
  'check',
  'outdent',
  'indent',
  '|',
  'quote',
  'line',
  'code',
  'inline-code',
  'insert-before',
  'insert-after',
  '|',
  'upload',
  'record',
  'table',
  '|',
  'undo',
  'redo',
  '|',
  'edit-mode',
  'content-theme',
  'code-theme',
  'export',
  {
    name: 'more',
    toolbar: [
      'fullscreen',
      'both',
      'preview',
      'info',
      'help',
    ],
  }
]

const initVditorEditor = () => {
  return new Vditor(vditorId.value, {
    height: props.height,
    width: "100%",
    mode: "ir", //所见即所得（wysiwyg）、即时渲染（ir）、分屏预览（sv）
    value: props.modelValue,
    placeholder: props.placeholder,
    toolbarConfig: {
      pin: true,
      // hide: true,
    },
    cache: {
      enable: false, // 是否使用 localStorage 进行缓存
    },
    lang: props.language as keyof II18n,
    theme: props.currentTheme,
    preview: {
      mode: "both", //显示模式
      delay: 10,
      actions: [],
      theme: {
        current: props.currentTheme == "classic" ? "light" : "dark",
      },
    },
    toolbar: toolbars,
    // vditor结构渲染完成后
    after: () => {
      // 这里根据传入的showPreview来设置vditor是否可输入内容
      props.showPreview && vditorEditor.value.disabled();
    },
    input: () => {
      emits("update:modelValue", vditorEditor.value.getValue(), vditorEditor.value.getHTML());
    },
    // 上传图片
    upload: uploader,
  });
}

const uploader = reactive<IUpload>({
  accept: "image/*", // 图片类型
  fieldName: "files", // 文件字段名
  extraData: props.extraData, // 要携带的额外的formData参数
  max: 10 * 1024 * 1024,
  multiple: true,
  withCredentials: false,
  // 图片上传校验，可以校验图片大小及类型
  validate(files) {
    const isLt10M = files[0].size / 1024 / 1024 < 10;
    if (!isLt10M) {
      ElMessage.error({
        message: "上传图片大小不能超过 10MB!"
      });
      return false;
    }
    if (!files[0].type.includes("image")) {
      ElMessage.error({
        message: "仅支持上传图片！"
      });
      return false;
    }
    return true;
  },
  handler: (files) => {
    const formData = new FormData();
    files.forEach((file) => {
      formData.append("files", file);
    });
    uploadMultiApi(formData).then((res: any) => {
      const code = res.code as number;
      const data = res.data as any;
      if (code === 0) {
        // 图片上传成功后，将图片地址插入到编辑器中
        data.forEach((item: any) => {
          vditorEditor.value.insertValue(`![${item.file_name}](${item.url})`);
        });
        emits("update:modelValue", vditorEditor.value.getValue(), vditorEditor.value.getHTML());
      } else {
        ElMessage.error({
          message: "图片上传失败"
        });
      }
    }).catch((err) => {
      console.log(err);
      ElMessage.error({
        message: "图片上传失败"
      });
    })
    return null;
  }
});

const getHtml = () => {
  return vditorEditor.value.getHTML();
}

defineExpose({
  getHtml
})
</script>

<style scoped lang="scss">
:deep(.vditor) {
  width: 100% !important;
}
:deep(.vditor-toolbar) {
  padding-left: 10px !important;
}
:deep(.vditor-reset) {
  padding: 10px !important;
  width: 100% !important;
}
</style>
